#pragma once

#include "Point.hpp"

namespace MetricSpaceBenchmark::MLIndex::LIMS {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // each reference point
    class Ref_Point {
    public:
        Point point;
        double r{};
        double r_low{};

        vector<double> dis;    // 距离数组,存储与其他点的距离

        vector<vector<double> > dict_circle;

        // polynomial regression model coefficients of this reference point
        vector<double> coeffs;

        Ref_Point() = default;

        Ref_Point(Point &point, double r, double r_low) {
            this->point = point;
            this->r = r;
            this->r_low = r_low;
        }

        void setDisArr(vector<double> &dis) {
            this->dis = dis;
        }

        void setDict(vector<vector<double>> &dict) {
            this->dict_circle = dict;
        }

        void setCoeffs(vector<double> &coeffs) {
            this->coeffs = coeffs;
        }
    };

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // main reference point of each cluster
    class mainRef_Point {
    public:
        Point point;      // 簇心
        double r{};       // 簇大半径
        double r_low{};   // 簇低半径

        vector<Ref_Point> ref_points;  // 存储簇内其余参考点
        vector<double> dis;            // 主要参考点到簇内其他点的距离

        vector<Point> iValuePts;       // 按 i 值排序的点

        // polynomial regression model coefficients of this reference point
        vector<double> coeffs;

        // list for insert point
        vector<InsertPt> insert_list;

        // store the function to fit distribute of i value list
        // y = ax + b
        double a{}, b{};
        int err_min{}, err_max{};

        // lower and upper of each circle
        vector<vector<double> > dict_circle;

        mainRef_Point() = default;

        mainRef_Point(Point &point, double r, double r_low, vector<Ref_Point> &ref_points) {
            this->point = point;
            this->r = r;
            this->r_low = r_low;
            this->ref_points = ref_points;
        }

        void setMainRefDisArr(vector<double> &dis) {
            this->dis = dis;
        }

        void setDict(vector<vector<double> > &dict) {
            this->dict_circle = dict;
        }

        void setIValuePts(vector<Point> &iValuePts) {
            this->iValuePts = iValuePts;
        }

        void setInsertPt(vector<InsertPt> &insert_list) {
            this->insert_list = insert_list;
        }

        void setLinear(double a, double b, int err_min, int err_max) {
            this->a = a;
            this->b = b;
            this->err_min = err_min;
            this->err_max = err_max;
        }

        void setCoeffs(vector<double> &coeffs) {
            this->coeffs = coeffs;
        }
    };

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // all reference point of whole data
    class Ref_Set {
    public:
        vector<mainRef_Point> ref_set;

        Ref_Set() = default;

        explicit Ref_Set(vector<mainRef_Point> &ref_set) {
            this->ref_set = ref_set;
        }
    };
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
